fix(config): negatively cache deterministic hosted config rejections and stop reporting 4xx errors - #3719
Conversation
…and stop reporting 4xx errors A hosted veryfront.config that the declarative evaluator deterministically rejects (e.g. forbidden-capability: unsupported-call) was re-read, re-hashed and re-sent to the evaluator worker on every request, because only successful evaluations were cached. Each per-request rethrow at the renderer.request boundary also produced a Sentry event even though CONFIG_PARSE_ERROR is a status-400 tenant-content failure. - Add a negative cache next to the positive hosted config cache, keyed by the same source-digest/policy/fingerprint cache key so a corrected config or a new release self-invalidates the entry. Worker-phase and retryable failures are never cached. - Treat client-class (4xx) VeryfrontErrors as expected in captureApplicationError so tenant-content failures no longer flood the error tracker; they remain logged at their throw sites. Fixes VERYFRONT-SERVER-E
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughChangesHosted configuration negative cache
Application-error classification
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: 🔵 Low · up to The PR adds deterministic rejection caching and stops reporting 4xx application errors; it is otherwise mergeable, but suppressing all 4xx errors could hide genuine server-side failures, so owner awareness or follow-up to narrow reportable cases is warranted. Sequence Diagram(s)sequenceDiagram
participant HostedSourceEvaluation
participant HostedConfigFailureCache
participant HostedConfigurationFlight
HostedSourceEvaluation->>HostedConfigFailureCache: Check project key and revision
HostedSourceEvaluation->>HostedConfigurationFlight: Evaluate when no cached failure exists
HostedConfigurationFlight->>HostedConfigFailureCache: Store deterministic failure
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
📦 Client bundle boundary
A server module in a client graph aborts hydration in the browser. New leaks fail CI; known leaks are tracked in |
The application error capture change shifted exported observability source anchors, and CI checks generated API reference files with the pinned Deno 2.7.7 toolchain. Regenerating only the stale observability reference keeps the stacked PR narrow while clearing the failing docs check. Constraint: PR #3723 is stacked on this branch, so the fix must avoid broad generated churn. Rejected: Commit docs generated by local Deno 2.7.12 | it rewrote anchors across 42 files and did not match CI's pinned generator output. Confidence: high Scope-risk: narrow Tested: PATH=/tmp/deno-2.7.7-aarch64-apple-darwin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/pmk/env/global/bin:/Library/Apple/usr/bin:/Applications/VMware Fusion.app/Contents/Public:/opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/codex-path:/Users/kojiwakayama/.codex/tmp/arg0/codex-arg0xChlGW:/private/tmp/claude-501/-Users-kojiwakayama-Documents-CODE-veryfront-platform-veryfront-code/9f9d23dd-dfdc-4463-9a99-bd5a663046c9/scratchpad/idx09/deno277/bin:/private/tmp/claude-501/-Users-kojiwakayama-Documents-CODE-veryfront-platform-veryfront-code/9f9d23dd-dfdc-4463-9a99-bd5a663046c9/scratchpad/idx13/deno277/bin:/private/tmp/claude-501/-Users-kojiwakayama-Documents-CODE-veryfront-platform-veryfront-code/9f9d23dd-dfdc-4463-9a99-bd5a663046c9/scratchpad/idx26-deno277/bin:/Users/kojiwakayama/Documents/CODE/agent-lab/.venv/bin:/Users/kojiwakayama/.veryfront/bin:/Users/kojiwakayama/.opencode/bin:/Users/kojiwakayama/.local/bin:/Users/kojiwakayama/.antigravity/antigravity/bin:/opt/homebrew/share/google-cloud-sdk/bin:/opt/homebrew/opt/openjdk/bin:/Users/kojiwakayama/.bun/bin:/Users/kojiwakayama/.krew/bin:/Applications/Visual Studio Code.app/Contents/Resources/app/bin:/Users/kojiwakayama/.nvm/versions/node/v24.18.0/bin:/Users/kojiwakayama/.cargo/bin:/Applications/Docker.app/Contents/Resources/bin/:/Users/kojiwakayama/.lmstudio/bin:/Applications/Warp.app/Contents/Resources/bin deno task lint:ci Tested: PATH=/tmp/deno-2.7.7-aarch64-apple-darwin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/pmk/env/global/bin:/Library/Apple/usr/bin:/Applications/VMware Fusion.app/Contents/Public:/opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/codex-path:/Users/kojiwakayama/.codex/tmp/arg0/codex-arg0xChlGW:/private/tmp/claude-501/-Users-kojiwakayama-Documents-CODE-veryfront-platform-veryfront-code/9f9d23dd-dfdc-4463-9a99-bd5a663046c9/scratchpad/idx09/deno277/bin:/private/tmp/claude-501/-Users-kojiwakayama-Documents-CODE-veryfront-platform-veryfront-code/9f9d23dd-dfdc-4463-9a99-bd5a663046c9/scratchpad/idx13/deno277/bin:/private/tmp/claude-501/-Users-kojiwakayama-Documents-CODE-veryfront-platform-veryfront-code/9f9d23dd-dfdc-4463-9a99-bd5a663046c9/scratchpad/idx26-deno277/bin:/Users/kojiwakayama/Documents/CODE/agent-lab/.venv/bin:/Users/kojiwakayama/.veryfront/bin:/Users/kojiwakayama/.opencode/bin:/Users/kojiwakayama/.local/bin:/Users/kojiwakayama/.antigravity/antigravity/bin:/opt/homebrew/share/google-cloud-sdk/bin:/opt/homebrew/opt/openjdk/bin:/Users/kojiwakayama/.bun/bin:/Users/kojiwakayama/.krew/bin:/Applications/Visual Studio Code.app/Contents/Resources/app/bin:/Users/kojiwakayama/.nvm/versions/node/v24.18.0/bin:/Users/kojiwakayama/.cargo/bin:/Applications/Docker.app/Contents/Resources/bin/:/Users/kojiwakayama/.lmstudio/bin:/Applications/Warp.app/Contents/Resources/bin deno test --preload=src/testing/preload.ts --no-check --allow-all --unstable-worker-options --unstable-net src/config/loader.test.ts src/observability/application-errors.test.ts Tested: PATH=/tmp/deno-2.7.7-aarch64-apple-darwin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/pmk/env/global/bin:/Library/Apple/usr/bin:/Applications/VMware Fusion.app/Contents/Public:/opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/codex-path:/Users/kojiwakayama/.codex/tmp/arg0/codex-arg0xChlGW:/private/tmp/claude-501/-Users-kojiwakayama-Documents-CODE-veryfront-platform-veryfront-code/9f9d23dd-dfdc-4463-9a99-bd5a663046c9/scratchpad/idx09/deno277/bin:/private/tmp/claude-501/-Users-kojiwakayama-Documents-CODE-veryfront-platform-veryfront-code/9f9d23dd-dfdc-4463-9a99-bd5a663046c9/scratchpad/idx13/deno277/bin:/private/tmp/claude-501/-Users-kojiwakayama-Documents-CODE-veryfront-platform-veryfront-code/9f9d23dd-dfdc-4463-9a99-bd5a663046c9/scratchpad/idx26-deno277/bin:/Users/kojiwakayama/Documents/CODE/agent-lab/.venv/bin:/Users/kojiwakayama/.veryfront/bin:/Users/kojiwakayama/.opencode/bin:/Users/kojiwakayama/.local/bin:/Users/kojiwakayama/.antigravity/antigravity/bin:/opt/homebrew/share/google-cloud-sdk/bin:/opt/homebrew/opt/openjdk/bin:/Users/kojiwakayama/.bun/bin:/Users/kojiwakayama/.krew/bin:/Applications/Visual Studio Code.app/Contents/Resources/app/bin:/Users/kojiwakayama/.nvm/versions/node/v24.18.0/bin:/Users/kojiwakayama/.cargo/bin:/Applications/Docker.app/Contents/Resources/bin/:/Users/kojiwakayama/.lmstudio/bin:/Applications/Warp.app/Contents/Resources/bin deno fmt --check docs/api-reference/veryfront/observability.md src/config/loader.ts src/config/loader.test.ts src/observability/application-errors.ts src/observability/application-errors.test.ts Tested: git diff --check
The tenant capture branch is stacked on fix/sentry-veryfront-server-e, and the base advanced after the tenant-build classifier fix landed. Merge the updated base non-destructively so the PR tests and merge base reflect the current stack without rewriting the branch. Constraint: Do not rebase or force-push the stacked PR branch. Rejected: Rebase onto the updated base | would rewrite the PR branch history. Confidence: high Scope-risk: narrow Directive: Keep #3723 stacked on #3719 until the lead asks to unstack or merge. Tested: pending post-merge verification
The stacked config prerequisite landed on main as a squash commit, so this merge preserves the tenant-error classifier and its regressions while accepting the released config and documentation state. Generated observability references were rebuilt with the CI-pinned Deno toolchain after resolving the overlapping application-error test. Constraint: #3719 merged by squash, so its branch commits are not ancestors of main Rejected: Rebase or force-push the feature branch | rewriting reviewed history would make the repair harder to audit Confidence: high Scope-risk: narrow Directive: Keep framework build failures error-level when changing tenant classification Tested: focused observability, pipeline, MDX compiler, and config suites; pinned API-reference generation; fmt; lint; typecheck; diff-check Not-tested: full pre-push hook runs on the resulting merge commit during push
Fixes VERYFRONT-SERVER-E (1,682 events / 7 users over 8 days, ongoing).
Root cause
A tenant's hosted
veryfront.configuses a construct outside the declarative subset (any property access /new— e.g.routes.mode,process.env.X— maps toforbidden-capability: unsupported-call). The rejection is correct and deterministic (security boundary; no full-JS fallback for hosted tenants by design), but nothing about it was remembered: every request re-read source, re-spawned a permissionless worker, re-parsed with Babel, and re-rejected — 1,682 Sentry events, and a hammered broken config burns the 2-slot evaluator worker pool, pushing other tenants into SERVICE_OVERLOADED.Fix
config-failure-cache) for deterministicDeclarativeConfigEvaluationErrorrejections, keyed by the existinghostedCacheKey(configPath ‖ sourceDigest ‖ policyVersion ‖ fingerprint) — exactly the right key: a source-bound rejection can never become a success without the digest changing. Retryable infra failures (worker-timeout/overloaded) are NOT cached.isExpectedApplicationError: 4xx VeryfrontErrors are no longer captured to Sentry (the tenant's 400 is their bug, not ours).Testing (red-green TDD)
Four new negative-caching tests in
loader.test.ts(deterministic rejection served from cache, exact production message asserted, infra failures still retried) +application-errors.test.tscoverage; all fail on pre-fix src (adversarial revert-check), pass at HEAD (109 steps loader, 14 passed observability).Reviewer notes (from adversarial verification)
Note: the stacked PR
fix/sentry-tenant-error-capturebuilds on this branch.Summary by CodeRabbit
Bug Fixes
Documentation
Tests